﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using KOPLibrary.AutoTemplateDesign;
using Microsoft.Office.Interop.Word;
using KOPLibrary.Exceptions;
using KOPLibrary.PreferenceManagement;
using KOPLibrary.TemplateManagement;
using KOPLibrary.DataManagement;

namespace KOPLibrary.Forms
{
    public partial class TemplateDesigner : Form
    {
        TextStyleList FormStyleList;
        TemplateDesignTable TemplateDesignList;
        Microsoft.Office.Interop.Word.Application app = null;
        AbstractData exceldata = null;
        bool nocontent = false;
        public Document ResultDocument = null;
        WordManager manager;
        public TemplateDesigner(Microsoft.Office.Interop.Word.Application apl, TemplateType type)
        {
            InitializeComponent();
            InitUI(apl, type);

        }

        public TemplateDesigner(Microsoft.Office.Interop.Word.Application apl, TemplateType type, AbstractData data)
        {
            InitializeComponent();
            exceldata = data;
            InitUI(apl, type);
        }

        public TemplateDesigner(Microsoft.Office.Interop.Word.Application apl, TemplateType type, AbstractData data, bool NoContent)
        {
            InitializeComponent();
            exceldata = data;
            nocontent = NoContent;
            InitUI(apl, type);
        }

        private void InitUI(Microsoft.Office.Interop.Word.Application apl, TemplateType type)
        {
            app = apl ?? new Microsoft.Office.Interop.Word.Application();
            manager = new WordManager(app);
            FormStyleList = new TextStyleList();
            TemplateDesignList = new TemplateDesignTable();
            List<string> halign = GetAligmentFriendlyList();
            List<string> borderstyle = GetBorderStyleFriendlyList();
            List<string> controltype = GetConrolTypeFriendlyList();
            List<KeyValuePair<string, string>> stylelist = GetStyleList();
            ctlHeaderAlignment.DataSource = halign.ToArray();
            ctlLabelAlignment.DataSource = halign.ToArray();
            ctlFooterAlignment.DataSource = halign.ToArray();
            ctlControlAlignment.DataSource = halign.ToArray();
            ctlBorderType.DataSource = borderstyle;
            ctlColumnCount.SelectedIndex = 0;
            ctlBorderThickness.SelectedIndex = 0;
            ctlDataType.DataSource = controltype;
            ctlStyles.DataSource = stylelist;
            if (type == TemplateType.Excel)
            {
                ctlRemoveControl.Visible = false;
                ctllDeleteAllControl.Visible = false;
                ctlSaveAsTemplate.Visible = false;
                ctlOpenAsDocument.Visible = false;
                ctlAddGroupBox.Visible = false;
                ctlExceltoWord.Visible = true;
                if (nocontent)
                {
                    ctlPageBreakCheckbox.Visible = false;
                    ctlCreateWordForm.Location = new System.Drawing.Point(5, 20);
                    ctlExceltoWord.Width = 160;
                    ctlExceltoWord.Left += 243;
                }
                foreach (string stritem in exceldata.Columns)
                {
                    TemplateDesignControl control = new TemplateDesignControl(Guid.NewGuid(), stritem, ControlType.String, AutoTemplateDesign.HorizontalAlignment.Left, AutoTemplateDesign.HorizontalAlignment.Left, Guid.Empty);
                    TemplateDesignList.Controls.Add(control);
                    ListViewItem item = new ListViewItem();
                    item.Tag = control.Id;
                    item.Text = control.LabelTitle;
                    item.SubItems.Add(GetControlTypeFriendly(control.Type));
                    item.SubItems.Add(GetAlignmentFriendly(control.LabelAlignment));
                    item.SubItems.Add(GetAlignmentFriendly(control.ControlAlignment));
                    ctlControlListView.Items.Add(item);
                }
            }
        }

        private List<KeyValuePair<string, string>> GetStyleList()
        {
            int ctr = 1;
            List<KeyValuePair<string, string>> style = new List<KeyValuePair<string, string>>();
            var x = from en in Enum.GetNames(typeof(WdBuiltinStyle)) where en.Contains("StyleTable") select en;
            style.Add(new KeyValuePair<string, string>("Yok", "None"));
            foreach (string item in x)
            {
                style.Add(new KeyValuePair<string, string>("Style " + ctr.ToString(), item));
                ctr++;
            } return style;
        }

        private List<string> GetBorderStyleFriendlyList()
        {
            List<string> style = new List<string>();
            foreach (string x in Enum.GetNames(typeof(KOPLibrary.AutoTemplateDesign.BorderStyle)))
            {
                string name = string.Empty;
                switch (x)
                {
                    case "Single": { name = "Tekli"; break; }
                    case "Double": { name = "İkili"; break; }
                    case "Triple": { name = "Üçlü"; break; }
                    case "Dotted": { name = "Noktalı"; break; }
                    case "Dashed": { name = "Kesik Çizgili"; break; }
                }
                style.Add(name);
            }
            return style;
        }

        private string GetAlignmentFriendly(KOPLibrary.AutoTemplateDesign.HorizontalAlignment alg)
        {
            switch (alg)
            {
                case KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Left:
                    return "Sol";
                case KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Center:
                    return "Orta";
                case KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Right:
                    return "Sağ";
                default:
                    return "Sol";
            }
        }
        private List<string> GetAligmentFriendlyList()
        {
            List<string> halign = new List<string>();
            foreach (string x in Enum.GetNames(typeof(KOPLibrary.AutoTemplateDesign.HorizontalAlignment)))
            {
                System.Data.DataTable dt = new System.Data.DataTable();
                string name = string.Empty;
                switch (x)
                {
                    case "Left": { name = "Sol"; break; }
                    case "Center": { name = "Orta"; break; }
                    case "Right": { name = "Sağ"; break; }
                }
                halign.Add(name);
            }
            return halign;
        }

        private void ctlStyleManageButton_Click(object sender, EventArgs e)
        {
            ShowDesignManager();
        }


        private void ShowDesignManager()
        {
            StyleManager stylemanager = new StyleManager(FormStyleList);
            if (stylemanager.ShowDialog() == DialogResult.OK)
            {
                FormStyleList = stylemanager.StyleList;
                BindStyleList();
            }
        }

        private void BindStyleList()
        {
            string key;
            List<KeyValuePair<string, Guid>> list = new List<KeyValuePair<string, Guid>>();
            foreach (TextStyle item in FormStyleList)
            {
                key = string.Format("{0},{1}{2}{3}pt", item.FontName, item.Bold ? "Kalın," : string.Empty, item.Italic ? "İtalik," : string.Empty, item.FontSize);
                KeyValuePair<string, Guid> pair = new KeyValuePair<string, Guid>(key, item.Id);
                list.Add(pair);
            }
            ctlHeaderStyle.DataSource = list.ToArray();
            ctlFooterStyle.DataSource = list.ToArray();
            ctlControlStyle.DataSource = list.ToArray();
        }
        private void ctlSaveAsTemplate_Click(object sender, EventArgs e)
        {
            if (ctlControlListView.Items.Count < 1)
            {
                MessageBox.Show("En az bir alan gereklidir", "Uyarı");
                return;
            }
            Microsoft.Office.Interop.Word.Document doc = manager.CreateWordDocument();
            ProcessDocument(doc, null);
            ResultDocument = doc;
            SaveDocumentAsTemplate(doc);
            this.Close();
        }

        private void SaveDocumentAsTemplate(Document doc)
        {
            object path = string.Empty;
            object missing = Type.Missing;
            object trueparam = true;
            object falseparam = false;
            using (SaveFileDialog sfd = new SaveFileDialog())
            {
                sfd.InitialDirectory = PreferenceManager.GetDefaulTemplatePath(KOPLibrary.TemplateManagement.TemplateType.Word);
                sfd.Title = "Şablon Kaydet";
                sfd.Filter = "Word şablon dosyası|*.dotx";
                sfd.AddExtension = true;
                sfd.DefaultExt = "dotx";
                sfd.OverwritePrompt = true;
                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        path = sfd.FileName;
                        doc.SaveAs(ref path, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                    }
                    catch (Exception ee)
                    {
                        ExceptionManager.ShowException(ee);
                    }
                }
            }
        }

        private void ProcessDocument(Document doc, object[] data)
        {
            int controlcount = ctlControlListView.Items.Count;
            TemplateDesignList.BorderThickness = ctlBorderThickness.SelectedItem.ToString();
            TemplateDesignList.TableBorderStyle = GetBorderStyleDeveloperFriendly(ctlBorderType.SelectedItem.ToString());
            object start = app.Selection.End;
            object end = app.Selection.End;
            object missing = Type.Missing;
            Range tablerange = doc.Range(ref start, ref end);
            int colcount = System.Convert.ToInt32(ctlColumnCount.SelectedItem);
            int rowcount = (int)Math.Ceiling(((double)controlcount / (double)(colcount / 2)));
            if (!string.IsNullOrEmpty(ctlFooterText.Text.Trim())) rowcount++;
            if (!string.IsNullOrEmpty(ctlHeaderText.Text.Trim())) rowcount++;
            Table controltable = tablerange.Tables.Add(tablerange, rowcount, colcount, ref missing, ref missing);
            TextDecoration style = new TextDecoration();
            #region Header
            if (!string.IsNullOrEmpty(ctlHeaderText.Text.Trim()))
            {
                try { style.FontId = (Guid)ctlHeaderStyle.SelectedValue; }
                catch { style.FontId = Guid.Empty; }
                style.HAlignment = GetAlignmentDeveloperFriendly(ctlHeaderAlignment.SelectedItem.ToString());
                controltable.Rows[1].Cells.Merge();
                controltable.Rows[1].Range.Text = ctlHeaderText.Text.Trim();
                SetTextStyleToRange(controltable.Rows[1].Range, style);
            }
            #endregion
            #region CreateTable
            int temp = (!string.IsNullOrEmpty(ctlFooterText.Text.Trim())) ? rowcount - 1 : rowcount;
            int tempstart = (!string.IsNullOrEmpty(ctlHeaderText.Text.Trim())) ? 2 : 1;
            if (controlcount > 0)
            {
                TemplateDesignControl tempcontrol = null;
                ContentControl tempcontentcontrol;
                int ctr = 0, controlctr = 0;
                for (int i = tempstart; i <= temp; i++)
                {
                    for (int j = 1; j <= colcount; j++)
                    {
                        if ((j % 2) == 0)
                        {
                            ctr++;
                            continue;
                        }
                        try
                        { tempcontrol = TemplateDesignList.Controls[ctr]; }
                        catch
                        { ;}
                        controltable.Cell(i, j).Range.Text = tempcontrol.LabelTitle;
                        SetTextStyleToRange(controltable.Cell(i, j).Range, new TextDecoration(tempcontrol.FontStyleId, tempcontrol.LabelAlignment));
                        controltable.Cell(i, j).VerticalAlignment = WdCellVerticalAlignment.wdCellAlignVerticalCenter;
                        tempcontentcontrol = controltable.Cell(i, j + 1).Range.ContentControls.Add(GetContentControlType(tempcontrol.Type), ref missing);
                        if (data != null && data[controlctr] != null && controlctr < data.Length)
                        {
                            if (!nocontent) tempcontentcontrol.Range.Text = data[controlctr].ToString();
                            controlctr++;
                        }
                        controltable.Cell(i, j + 1).VerticalAlignment = WdCellVerticalAlignment.wdCellAlignVerticalCenter;
                        SetTextStyleToRange(controltable.Cell(i, j + 1).Range, new TextDecoration(tempcontrol.FontStyleId, tempcontrol.ControlAlignment));
                        tempcontentcontrol.Title = tempcontrol.LabelTitle;
                    }
                }
                controltable.Borders.InsideLineStyle = GetBorderStyleOfficeFriendly(TemplateDesignList.TableBorderStyle);
                controltable.Borders.OutsideLineStyle = GetBorderStyleOfficeFriendly(TemplateDesignList.TableBorderStyle);
                try
                {
                    controltable.Borders.InsideLineWidth = GetBorderWidthOfficeFriendly(TemplateDesignList.BorderThickness);
                    controltable.Borders.OutsideLineWidth = GetBorderWidthOfficeFriendly(TemplateDesignList.BorderThickness);
                }
                catch { ;}
                controltable.Spacing = 0;
                string styletype = ctlStyles.SelectedValue.ToString();
                if (styletype != "None")
                {
                    object sty = Enum.Parse(typeof(WdBuiltinStyle), ctlStyles.SelectedValue.ToString());
                    controltable.set_Style(ref sty);
                }

            }

            #endregion

            #region Footer
            if (!string.IsNullOrEmpty(ctlFooterText.Text.Trim()))
            {
                try { style.FontId = (Guid)ctlFooterStyle.SelectedValue; }
                catch { style.FontId = Guid.Empty; }
                style.HAlignment = GetAlignmentDeveloperFriendly(ctlFooterAlignment.SelectedItem.ToString());
                controltable.Rows[rowcount].Cells.Merge();
                controltable.Rows[rowcount].Range.Text = ctlFooterText.Text.Trim();
                SetTextStyleToRange(controltable.Rows[rowcount].Range, style);
            }
            #endregion
        }

        private WdParagraphAlignment GetAlignmentOfficeFriendly(KOPLibrary.AutoTemplateDesign.HorizontalAlignment alg)
        {
            WdParagraphAlignment algn;
            switch (alg)
            {
                case KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Left:
                    {
                        algn = WdParagraphAlignment.wdAlignParagraphLeft;
                        break;
                    }
                case KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Center:
                    {
                        algn = WdParagraphAlignment.wdAlignParagraphCenter;
                        break;
                    }
                case KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Right:
                    {
                        algn = WdParagraphAlignment.wdAlignParagraphRight;
                        break;
                    }
                default:
                    {
                        algn = WdParagraphAlignment.wdAlignParagraphLeft;
                        break;
                    }
            }
            return algn;
        }

        private WdLineWidth GetBorderWidthOfficeFriendly(string p)
        {
            switch (p)
            {
                case "0,25": return WdLineWidth.wdLineWidth025pt;
                case "0,50": return WdLineWidth.wdLineWidth050pt;
                case "0,75": return WdLineWidth.wdLineWidth075pt;
                case "1,00": return WdLineWidth.wdLineWidth100pt;
                case "1,50": return WdLineWidth.wdLineWidth150pt;
                case "2,25": return WdLineWidth.wdLineWidth225pt;
                case "3,00": return WdLineWidth.wdLineWidth300pt;
                case "4,50": return WdLineWidth.wdLineWidth450pt;
                case "6,00": return WdLineWidth.wdLineWidth600pt;
                default: return WdLineWidth.wdLineWidth025pt;
            }
        }

        private KOPLibrary.AutoTemplateDesign.BorderStyle GetBorderStyleDeveloperFriendly(string p)
        {
            switch (p)
            {
                case "Tekli": return KOPLibrary.AutoTemplateDesign.BorderStyle.Single;
                case "İkili": return KOPLibrary.AutoTemplateDesign.BorderStyle.Double;
                case "Üçlü": return KOPLibrary.AutoTemplateDesign.BorderStyle.Triple;
                case "Noktalı": return KOPLibrary.AutoTemplateDesign.BorderStyle.Dotted;
                case "Kesik Çizgili": return KOPLibrary.AutoTemplateDesign.BorderStyle.Dashed;
                default: return KOPLibrary.AutoTemplateDesign.BorderStyle.Single;
            }
        }

        private WdLineStyle GetBorderStyleOfficeFriendly(KOPLibrary.AutoTemplateDesign.BorderStyle borderStyle)
        {
            switch (borderStyle)
            {
                case KOPLibrary.AutoTemplateDesign.BorderStyle.Dotted:
                    return WdLineStyle.wdLineStyleDot;
                case KOPLibrary.AutoTemplateDesign.BorderStyle.Dashed:
                    return WdLineStyle.wdLineStyleDashDot;
                case KOPLibrary.AutoTemplateDesign.BorderStyle.Single:
                    return WdLineStyle.wdLineStyleSingle;
                case KOPLibrary.AutoTemplateDesign.BorderStyle.Double:
                    return WdLineStyle.wdLineStyleDouble;
                case KOPLibrary.AutoTemplateDesign.BorderStyle.Triple:
                    return WdLineStyle.wdLineStyleTriple;
                default:
                    return WdLineStyle.wdLineStyleNone;
            }
        }

        private WdContentControlType GetContentControlType(ControlType controlType)
        {
            switch (controlType)
            {
                case ControlType.String:
                    return WdContentControlType.wdContentControlText;
                case ControlType.DateTime:
                    return WdContentControlType.wdContentControlDate;
                case ControlType.Picture:
                    return WdContentControlType.wdContentControlPicture;
                default:
                    return WdContentControlType.wdContentControlText;
            }
        }

        private KOPLibrary.AutoTemplateDesign.HorizontalAlignment GetAlignmentDeveloperFriendly(string p)
        {
            switch (p)
            {
                case "Sol": { return KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Left; }
                case "Sağ": { return KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Right; }
                case "Orta": { return KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Center; }
                default: { return KOPLibrary.AutoTemplateDesign.HorizontalAlignment.Left; }
            }
        }

        private void SetTextStyleToRange(Range range, TextDecoration style)
        {
            range.ParagraphFormat.Alignment = GetAlignmentOfficeFriendly(style.HAlignment);
            if (style.FontId == Guid.Empty) return;
            TextStyle tempfont = FormStyleList[style.FontId];
            range.Font.Name = tempfont.FontName;
            range.Font.Size = (float)tempfont.FontSize;
            range.Font.Bold = System.Convert.ToInt32(tempfont.Bold);
            range.Font.Italic = System.Convert.ToInt32(tempfont.Italic);
        }

        private void ctlAddControl_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(ctlControlLabelName.Text))
            {
                MessageBox.Show("Alan adı boş olamaz", "Uyarı");
                return;
            }
            TemplateDesignControl control = new TemplateDesignControl();
            control.Id = Guid.NewGuid();
            control.ControlAlignment = GetAlignmentDeveloperFriendly(ctlControlAlignment.SelectedItem.ToString());
            try { control.FontStyleId = (Guid)ctlControlStyle.SelectedValue; }
            catch { control.FontStyleId = Guid.Empty; }
            control.LabelAlignment = GetAlignmentDeveloperFriendly(ctlLabelAlignment.SelectedItem.ToString());
            control.LabelTitle = ctlControlLabelName.Text.Trim();
            control.Type = GetControlTypeDeveloperFriendly(ctlDataType.SelectedItem.ToString());
            TemplateDesignList.Controls.Add(control);
            ListViewItem item = new ListViewItem();
            item.Tag = control.Id;
            item.Text = control.LabelTitle;
            item.SubItems.Add(ctlDataType.SelectedItem.ToString());
            item.SubItems.Add(ctlLabelAlignment.SelectedItem.ToString());
            item.SubItems.Add(ctlControlAlignment.SelectedItem.ToString());
            if (ctlControlStyle.SelectedItem != null && ctlControlStyle.SelectedItem.ToString().Trim() != string.Empty)
                item.SubItems.Add(((KeyValuePair<string, Guid>)ctlControlStyle.SelectedItem).Key.ToString());
            ctlControlListView.Items.Add(item);
            ctlControlLabelName.Text = "";
        }

        private string GetControlTypeFriendly(KOPLibrary.AutoTemplateDesign.ControlType type)
        {
            switch (type)
            {
                case ControlType.String:
                    return "Metin";
                case ControlType.DateTime:
                    return "Tarih";
                case ControlType.Picture:
                    return "Resim";
                default:
                    return "Metin";
            }
        }
        private List<string> GetConrolTypeFriendlyList()
        {
            List<string> controltype = new List<string>();
            foreach (string x in Enum.GetNames(typeof(KOPLibrary.AutoTemplateDesign.ControlType)))
            {
                string name = string.Empty;
                switch (x)
                {
                    case "String": { name = "Metin"; break; }
                    case "DateTime": { name = "Tarih"; break; }
                    case "Picture": { name = "Resim"; break; }
                }
                controltype.Add(name);
            }
            return controltype;
        }
        private ControlType GetControlTypeDeveloperFriendly(string p)
        {
            switch (p)
            {
                case "Metin": { return ControlType.String; }
                case "Tarih": { return ControlType.DateTime; }
                case "Resim": { return ControlType.Picture; }
                default: { return ControlType.String; }
            }
        }

        private void ctlControlListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (ctlControlListView.SelectedItems.Count == 0) return;
            ListViewItem item = (ctlControlListView.SelectedItems.Count == 1) ? ctlControlListView.SelectedItems[0] : ctlControlListView.SelectedItems[ctlControlListView.SelectedItems.Count - 1];
            ShowItemInEditor(TemplateDesignList[(Guid)item.Tag]);
        }

        private void ShowItemInEditor(TemplateDesignControl templateDesignControl)
        {
            ctlControlAlignment.SelectedIndex = ctlControlAlignment.Items.IndexOf(GetAlignmentFriendly(templateDesignControl.ControlAlignment));
            ctlControlLabelName.Text = templateDesignControl.LabelTitle;
            ctlLabelAlignment.SelectedItem = ctlLabelAlignment.Items.IndexOf(GetAlignmentFriendly(templateDesignControl.LabelAlignment));
            ctlDataType.SelectedItem = ctlDataType.Items.IndexOf(GetControlTypeFriendly(templateDesignControl.Type));
        }

        private void ctlRemoveControl_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in ctlControlListView.SelectedItems)
            {
                ctlControlListView.Items.Remove(item);
                DeleteStyle((Guid)item.Tag);
            }
        }

        private void DeleteStyle(Guid guid)
        {
            TemplateDesignList.Controls.Remove(TemplateDesignList[guid]);
        }

        private void ctllDeleteAllControl_Click(object sender, EventArgs e)
        {
            TemplateDesignList.Controls.Clear();
            ctlControlListView.Items.Clear();
        }

        private void ctlOpenAsDocument_Click(object sender, EventArgs e)
        {
            if (ctlControlListView.Items.Count < 1)
            {
                MessageBox.Show("En az bir alan gereklidir", "Uyarı");
                return;
            }
            Microsoft.Office.Interop.Word.Document doc = manager.CreateWordDocument();
            ProcessDocument(doc, null);
            doc.Application.ShowMe();
            ResultDocument = doc;
            this.Close();
        }

        private void ctlCreateWordForm_Click(object sender, EventArgs e)
        {
            ProgressForm progress = new ProgressForm();
            progress.Initialize(1, exceldata.Count, "Word ile iletişime geçiliyor ...", true, this);
            app.ScreenUpdating = false;
            app.Visible = true;
            Microsoft.Office.Interop.Word.Document doc = manager.CreateWordDocument();
            int ctr = 1;
            foreach (object[] item in exceldata.ItemArray)
            {
                progress.Update(string.Format("Aktarılıyor: {0} / {1}", progress.Current, (nocontent) ? 1 : exceldata.Count));
                if (progress.Canceled) break;
                ProcessDocument(doc, item);
                if (nocontent) break;
                app.Selection.EndKey(WdUnits.wdStory, WdMovementType.wdMove);
                if (ctlPageBreakCheckbox.Checked)
                {
                    if (ctr < exceldata.ItemArray.Count) app.Selection.Range.InsertBreak(WdBreakType.wdPageBreak);
                    ctr++;
                    app.Selection.EndKey(WdUnits.wdStory, WdMovementType.wdMove);
                }
                else
                {
                    app.Selection.TypeParagraph();
                }
            }
            progress.Done();
            app.ScreenUpdating = true;
            ResultDocument = doc;
            this.Close();
            app.Visible = true;
            doc.Activate();
            doc.Application.ShowMe();
        }


    }
}
